package com.meta.nd.util.json;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.meta.cache.NdCacheService;
import com.meta.common.ConstDef;
import com.meta.nd.util.NodeUtil;
import com.meta.nd.vo.Fd;
import com.meta.nd.vo.Fv;
import com.meta.nd.vo.Nd;
import com.meta.nd.vo.Nv;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NdJsonTool {
	
	private static NdCacheService ndCacheService; 
	
	public static void setNdCacheService( NdCacheService ndCacheService) {
		NdJsonTool.ndCacheService = ndCacheService;
	}
	
	private static ObjectNode nv2JsonNode(Nv nv,boolean createFvId ) {
	    ObjectMapper mapper = new ObjectMapper();
	    ObjectNode root = mapper.createObjectNode();
	    root.put("id", nv.getId());
	    root.put("parentId", nv.getParentId());
	    root.put("code", nv.getMetaNdCode());
	    root.put("operationFlag", nv.getOperationFlag());
	    
		 for ( Fv fv: nv.getFvs().values() ) {
			 
				if ( fv.getDataType().equals(ConstDef.DATA_TYPE_DATE )) {
					
					root.put(fv.getName(), NodeUtil.formatDate(fv.getRawDate()));
					
					
				} else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_DATETIME )) {
					
					root.put(fv.getName(), NodeUtil.formatDatetime(fv.getRawDate()));
					
					
				}
				
				else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_STRING ) ){
					
					boolean process =false;
					Nd nd = ndCacheService.getNd(nv.getMetaNdCode());
					if ( !process ) {
						
						if ( fv.getRawString() == null ) {
							root.put(fv.getName(), "");
						}
						else {
							root.put(fv.getName(), fv.getRawString());	
						}	
					}
				}
				else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_BOOLEAN ) ){
					root.put(fv.getName(), fv.getRawBool());
					
				}
				else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_INT )) {
					root.put(fv.getName(), fv.getRawInt());
				}
					
				else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_LONG ) ) {
					root.put(fv.getName(), fv.getRawLong());
					
				} 
				else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_FLOAT ) ) {
					root.put(fv.getName(), fv.getRawDouble())	;
				}
				else if ( fv.getDataType().equals(ConstDef.DATA_TYPE_STRING_LIST)){
					root.put(fv.getName(),fv.getRawStringList().toString());
				}
				else {
					throw new RuntimeException("不存在的数据类型：" + fv.getDataType());
				}
				
				if (createFvId )
					root.put(fv.getName() +"_id", fv.getId());
				
		 }
		 
		for (String childName: nv.getChildrenMap().keySet()	) {
			ArrayNode arrayNode = mapper.createArrayNode ();
			List<Nv> childNvs = nv.getChildNvs(childName);
			for ( Nv childNv : childNvs ) {
				JsonNode childNode = nv2JsonNode(childNv);
				arrayNode.add(childNode);
			}
			root.put(childName, arrayNode);
		}
	    
	    return root;  	
		
	}
	
	public static  String nvs2Json( List<Nv> nvs ) {
		
	    ObjectMapper mapper = new ObjectMapper();  
		ArrayNode arrayNode = mapper.createArrayNode ();
		
		for ( Nv nv : nvs ) {
			JsonNode childNode = nv2JsonNode(nv);
			arrayNode.add(childNode);
		}
		
		return arrayNode.toString();
		
	}
		
	
	private static ObjectNode nv2JsonNode(Nv nv ) {
		return nv2JsonNode(nv,true);
	}
	
	public static String createNvJson ( Nv nv ) {
		
		if ( nv == null )
			return null;
		else
			return nv2JsonNode(nv).toString();
	     
	   
	}
	
	
	public static String createNvsJson( List<Nv> nvs ) {
		
	    ObjectMapper mapper = new ObjectMapper();  
	    ArrayNode arrayNode = mapper.createArrayNode ();
	    
	    for (Nv nv : nvs ) {
	    	JsonNode node = nv2JsonNode(nv);
	    	arrayNode.add(node);
	    }
	    
	    return arrayNode.toString();
		
	}


public static Object  jsonNode2Fv( String dataType, JsonNode node ){
	Object value = null;
	if (node.isNull())
		return null;
	if ( dataType.equals(ConstDef.DATA_TYPE_STRING ) ){
		value = node.asText();
	}
	else if ( dataType.equals(ConstDef.DATA_TYPE_DATE )) {
		String text = node.asText();
		value = NodeUtil.parseDate(text);
	}else if ( dataType.equals(ConstDef.DATA_TYPE_DATETIME )) {
		String text = node.asText();
		value = NodeUtil.parseDatetime(text);
	}
	else if ( dataType.equals(ConstDef.DATA_TYPE_BOOLEAN ) ){
		value = node.asBoolean();
	}
	else if ( dataType.equals(ConstDef.DATA_TYPE_INT )) {
		value = node.asInt();
	}
	else if ( dataType.equals(ConstDef.DATA_TYPE_LONG ) ) {
		value = node.asLong();
	}
	else if ( dataType.equals(ConstDef.DATA_TYPE_FLOAT ) ) {
		value = node.asDouble();
	}
	else if ( dataType.equals(ConstDef.DATA_TYPE_STRING_LIST)){
		List<String> strListValue = new ArrayList<String>();
		for (final JsonNode oneNode : node) {
			strListValue.add(oneNode.asText());
		}
		value = strListValue;
	}else
	 {
		throw new RuntimeException("不存在的数据类型：" + dataType);
	}
	return value;
}
	
	public static Object  jsonNode2Fv( Fd fd, JsonNode node ) {
		return jsonNode2Fv(fd.getDataType(),node);
	}
	
	public static Nv jsonNode2Nv(String json) {
		
		ObjectMapper mapper = new ObjectMapper(); //转换器  
		JsonNode node = null;
		try {
			node = mapper.readValue(json.getBytes(), JsonNode.class);
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if ( node == null)
			
			return null;
		
		
		String code = node.get("code").asText();
		Nd nd = ndCacheService.getRootNd(code);
		

			
		Nv nv = NdJsonTool.jsonNode2Nv(nd, node);
	
		return nv;
		
	}

	
	public static Nv jsonNode2Nv( Nd nd,JsonNode node ) {
		Nv nv = NodeUtil.nd2Nv(nd);
		nv.setId(node.get("id").asLong());
		if(nv.getId() < 0 )
			nv.setId(0);	
		if(node.get("parentId")!=null && !node.get("parentId").isNull())
			nv.setParentId(node.get("parentId").asLong());
		nv.setMetaNdCode(node.get("__ndCode").asText());
		nv.setActualNdCode(node.get("__actualNdCode").asText());
		nv.setOperationFlag(node.get("operationFlag").asText());
		Iterator<String> iterator =  node.fieldNames();
		while (  iterator.hasNext() ) {
			String fdName = iterator.next();
			 if ( fdName.equals("id") ||
					 	fdName.equals("parentId")||
						fdName.equals("__ndName")||
						fdName.equals("__ndCode") ||
						fdName.equals("__dbMapCode") ||
					 fdName.equals("__actualNdCode") ||
						fdName.equals("operationFlag") )
				 continue;
			 if (nd.existByName(fdName ) ) {
				 Object value = jsonNode2Fv(nd.getFdByName(fdName).getDataType(),node.get(fdName));
				 nv.setFvByName(fdName, value);
			 }
			 else if ( nd.getChildNd(fdName) != null ){
				JsonNode childNodeArray = node.get(fdName);
				for (final JsonNode childNode : childNodeArray ) {
					 Nv childNv = jsonNode2Nv(nd.getChildNd(fdName),childNode);
					 nv.addChildNv(fdName, childNv);
				}
			 }
			 else if ( nd.isCursive() && nd.getNdName().equals(fdName)) {
				JsonNode childNodeArray = node.get(fdName);
				for (final JsonNode childNode : childNodeArray ) {
					 Nv childNv = jsonNode2Nv(nd,childNode);			 
					 nv.addChildNv(fdName, childNv);
				} 
			 }
			 else log.error("不存在名称:" + fdName);
		 }
		 return nv;
	}
	  

	
	


	


}
